package ru.mirent.url;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.ArgumentsProvider;
import org.junit.jupiter.params.provider.ArgumentsSource;

import java.net.URI;
import java.util.stream.Stream;

public class UrlCheckTest {

    @Test
    void positiveCheckTest() {
        URI uri = new UrlCheck().apply("https://www.google.com:443/search?sca_esv=f4da&sca_upv=1&q=Observer+pattern#imgrc=zVL2bLIFK12jZM");

        Assertions.assertEquals("https", uri.getScheme());
        Assertions.assertEquals("www.google.com", uri.getHost());
        Assertions.assertEquals("/search", uri.getPath());
        Assertions.assertEquals(443, uri.getPort());
        Assertions.assertEquals("sca_esv=f4da&sca_upv=1&q=Observer+pattern", uri.getQuery());
        Assertions.assertEquals("imgrc=zVL2bLIFK12jZM", uri.getFragment());
    }

    @ParameterizedTest
    @ArgumentsSource(PositiveTestData.class)
    void positiveTest(String url) {
        Assertions.assertDoesNotThrow(
                () -> new UrlCheck().apply(url)
        );
    }

    @ParameterizedTest
    @ArgumentsSource(NegativeTestData.class)
    void negativeTest(String url, String expectedErrorMessage) {
        RuntimeException failed = Assertions.assertThrows(RuntimeException.class,
                () -> new UrlCheck().apply(url)
        );
        Assertions.assertEquals(expectedErrorMessage, failed.getMessage());
    }

    private static class PositiveTestData implements ArgumentsProvider {
        @Override
        public Stream<? extends Arguments> provideArguments(ExtensionContext context) {
            return Stream.of(
                    Arguments.of("https://www.google.com/search?sca_esv=f4da&sca_upv=1&q=Observer+pattern#imgrc=zVL2bLIFK12jZM"),
                    Arguments.of("https://www.google.com:9080/search"),
                    Arguments.of("https://www.google.com"),
                    Arguments.of("https:/www.google.com"),
                    Arguments.of("https://www.google.com:"),
                    Arguments.of("https://www.google.com/search?sca_esv=")
            );
        }
    }

    private static class NegativeTestData implements ArgumentsProvider {
        @Override
        public Stream<? extends Arguments> provideArguments(ExtensionContext context) {
            return Stream.of(
                    Arguments.of("hrtps://www.google.com", "java.net.MalformedURLException: unknown protocol: hrtps"),
                    Arguments.of("https//www.google.com", "java.net.MalformedURLException: no protocol: https//www.google.com"),
                    Arguments.of("https://www.google.com\\", "java.net.URISyntaxException: Illegal character in authority at index 8: https://www.google.com\\")
            );
        }
    }
}
